package com.nengchuan.kbms.dfs.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.nengchuan.config.exception.NcException;
import com.nengchuan.kbms.common.AutoWrapper;
import com.nengchuan.kbms.common.DfsTreeNode;
import com.nengchuan.kbms.dfs.annotation.UserOperateLogger;
import com.nengchuan.kbms.dfs.entity.dto.*;
import com.nengchuan.kbms.dfs.entity.po.DataFile;
import com.nengchuan.kbms.dfs.entity.po.DataFileTagAttr;
import com.nengchuan.kbms.dfs.entity.po.DataFolder;
import com.nengchuan.kbms.dfs.entity.po.DataTag;
import com.nengchuan.kbms.dfs.entity.vo.DataFileVO;
import com.nengchuan.kbms.dfs.entity.vo.FileDetailVO;
import com.nengchuan.kbms.dfs.service.*;
import com.nengchuan.model.model.NcPageInfo;
import com.nengchuan.model.model.WrappedResult;
import com.nengchuan.util.IdGenUtils;
import com.nengchuan.util.MapperUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.net.URLEncoder;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 文件表 前端控制器
 * </p>
 *
 * @author abe
 * @since 2020-03-24
 */
@RestController
@RequestMapping("/background")
@Api(tags = "知识库数据后台管理 > 知识库系统后台管理系统 【进行中】")
public class BackgroundController {

    @Autowired
    private DataFileService dataFileService;

    @Autowired
    private DataFolderService dataFolderService;

    @Autowired
    private DataTagAttrService dataTagAttrService;

    @Autowired
    private DataFileTagAttrService dataFileTagAttrService;

    /**
     * TODO 如果 DataFilePageDTO 中未做限制，条件内容都为空，那么目前系统会对整个文件夹和文件进行sql like检索；
     * 这边后期必须做限制 ！！！
     */
    @PostMapping("/page")
    @ApiOperation(value = "文件（夹）列表")
    public WrappedResult<NcPageInfo<DataFileVO>> page(@RequestBody DataFilePageDTO pageDTO) {
        IPage<DataFileVO> pageList = dataFileService.folderAndFilePage(pageDTO);
        return WrappedResult.success(MapperUtils.mappingNcPage(pageList, DataFileVO.class));
    }

    @GetMapping("/file/data")
    @ApiOperation(value = "文件详情")
    public WrappedResult<FileDetailVO> data(@ApiParam(value = "文件id", required = true) @RequestParam Long id) {
        FileDetailVO fileDetailVO = dataFileService.getDetail(id);
        return WrappedResult.success(fileDetailVO);
    }

    // -------------- 文件 -------------------

    @PostMapping(value = "/file/upload")
    @ApiOperation(value = "文件上传")
    @UserOperateLogger(type = UserOperateLogger.Type.CREATE)
    public WrappedResult<DataFileVO> uploadFile(
            @ApiParam(value = "文件夹id", required = true) @RequestParam Long folderId,
            @ApiParam(value = "备注，描述") @RequestParam(required = false) String remark,
            MultipartFile file) throws Exception {
        DataFileUploadDTO dto = new DataFileUploadDTO();
        dto.setFolderId(folderId);
        dto.setRemark(remark);
        dto.setFileName(file.getOriginalFilename());
        dto.setFileSize(file.getSize());
        DataFileVO dataFileVO = dataFileService.uploadFile(dto, file.getInputStream());
        return WrappedResult.success(dataFileVO);
    }


    @PostMapping(value = "/file/resolve")
    @ApiOperation(value = "文件名解析")
    public WrappedResult<DataFileVO> resolveFileName(@ApiParam(value = "文件", required = true) @RequestParam("file") MultipartFile file,
                                                     @ApiParam(value = "文件夹名称", required = true) @RequestParam("folderName") String folderName) throws Exception {
        DataFileVO dataFileVO =  dataFileService.resolveFileName(file,folderName);
        return WrappedResult.success(dataFileVO);
    }


    @GetMapping(value = "/file/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    @ApiOperation(value = "文件下载")
    @UserOperateLogger(type = UserOperateLogger.Type.DOWNLOAD)
    public void downloadFile(
            @ApiParam(value = "文件id", required = true) @RequestParam Long id,
            HttpServletResponse response) {
        DownloadFileDTO dto = new DownloadFileDTO();
        dto.setId(id);
        // TODO 水印 ，密码等
        DataFile dataFile = dataFileService.getById(id);
        Objects.requireNonNull(dataFile, "文件不存在");
        try {
            String fileName = URLEncoder.encode(dataFile.getFileName(), "UTF-8");
            response.reset();
            response.setContentType("application/x-download");
            response.addHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
            dataFileService.downloadFile(dto, response.getOutputStream());
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    @GetMapping(value = "/file/preview", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    @ApiOperation(value = "文件预览")
    @UserOperateLogger(type = UserOperateLogger.Type.PREVIEW)
    public void previewFile(
            @ApiParam(value = "文件id", required = true) @RequestParam Long id,
            HttpServletResponse response) {
        DataFile dataFile = dataFileService.getById(id);
        Objects.requireNonNull(dataFile, "文件不存在");
        DownloadFileDTO dto = new DownloadFileDTO();
        dto.setId(id);
        try {
            response.reset();
//            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "inline; filename= file");
            dataFileService.downloadFile(dto, response.getOutputStream());
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    // ----------- 文件夹 ----------

    @PostMapping("/folder/save")
    @ApiOperation(value = "保存")
    @UserOperateLogger(type = UserOperateLogger.Type.CREATE_FOLDER)
    public WrappedResult<Long> save(@RequestBody DataFolderDTO dto) {
        return WrappedResult.success(dataFolderService.saveFolder(dto));
    }

    @PostMapping("/folder/update")
    @ApiOperation(value = "更新")
    @UserOperateLogger(type = UserOperateLogger.Type.UPDATE_FOLDER)
    public WrappedResult<Boolean> update(@RequestBody DataFolderDTO dto) {
        return WrappedResult.success(dataFolderService.updateFolder(dto));
    }

    @PostMapping("/folder/delete")
    @ApiOperation(value = "删除")
    public WrappedResult<Boolean> delete(@ApiParam(value = "文件（夹）id", required = true) @RequestParam Serializable id) {
        return WrappedResult.success(dataFolderService.removeFolder(id));
    }


    @GetMapping("/folder/tree")
    @ApiOperation(value = "文件夹树（层级结构）")
    public WrappedResult<List<DfsTreeNode>> tree(@ApiParam(value = "文件夹id", required = true) @RequestParam Long id) {
        return WrappedResult.success(dataFolderService.tree(id));
    }

    @GetMapping("/folder/simple-tree")
    @ApiOperation(value = "文件夹树（简单结构）")
    public WrappedResult<List<DfsTreeNode>> simpleTree(@ApiParam(value = "文件夹id", required = true) @RequestParam Long id) {
        return WrappedResult.success(dataFolderService.simpleTree(id));
    }

    @GetMapping("/folder/lazy-simple-tree")
    @ApiOperation(value = "文件夹树（简单结构，懒加载）")
    public WrappedResult<List<DfsTreeNode>> lazySimpleTree(@ApiParam(value = "文件夹id", required = true) @RequestParam Long id) {
        return WrappedResult.success(dataFolderService.lazySimpleTree(id));
    }

}
